// standing tree nodes
var caret;
var head;


var comcaret;
var comhead;
var slashMode=0; // to make sure there is only one slash mode in action
var slashFlag=0;

function heightCaret(caret) {
	switch (parseInt(caret.attr('level'))) {
		case 1:
		return 28;
		break;
		case 2:
		return 18;
		break;
		case 3:
		return 15;
		break;
		case 4:
		return 13;
		break;
		case 5:
		return 11;
		break;
		default:  // all lever above 5 returns 11
		return 11;
		break;
	}
}

function showCaretCommand() {

	$('#comcaret').css('left',comcaret.offset().left+parseInt(comcaret.attr('width')));
	$('#comcaret').css('top',comcaret.offset().top);
	if(comcaret.height()!=0) {
		$('#comcaret').css('height',parseInt(comcaret.attr('height')));	
	}
	else {
		$('#comcaret').css('height',heightCaret(comcaret));
		$('#comcaret').css('top',comcaret.offset().top-heightCaret(comcaret));
	}	
}

function showCaret() {
	
	var leftElement, rightElement;
	
//	alert(caret.attr("class")+caret.attr("flag"));
	
	$('#caret').css('left',caret.offset().left+parseInt(caret.attr('width')));
	$('#caret').css('top',caret.offset().top);
	if(caret.height()!=0) {
		$('#caret').css('height',parseInt(caret.attr('height')));	
	}
	else {
		$('#caret').css('height',heightCaret(caret));
		$('#caret').css('top',caret.offset().top-heightCaret(caret));
	}
	
	leftElement=caret.parent().children().first();
	rightElement=caret.parent().children().last();
	
	
	$('#left').css('left',leftElement.offset().left);
	$('#left').css('top',parseInt($('#caret').css('top').toString(),10)+parseInt(caret.attr('height'))-$('#left').height());

	$('#right').css('left',rightElement.offset().left+parseInt(rightElement.attr('width')));
	$('#right').css('top',parseInt($('#caret').css('top').toString(),10)+parseInt(caret.attr('height'))-$('#left').height());
	
	
}

function prepareEditor() {   //initialize the tree
	head=$('<div></div>').appendTo($('#compiled'));
	caret=$('<span></span>').appendTo(head);
	
	head.attr('level',0);
	head.attr('width',0);
	caret.attr('level',1);
//	caret.css('position',"absolute");
	caret.css('left',0);
	caret.css('bottom',$(window).height()/2);
	caret.attr('width',0);
	caret.attr('height',0);
	caret.attr('class',"starter");
	
	$('#symbol').hide();
	$('#command').hide();
	$('#comcaret').hide();
	slashFlag=0;
}

function prepareCommand(){


	
	$('#command').css('left',caret.offset().left+parseInt(caret.attr('width')));
	$('#symbol').css('left',caret.offset().left+parseInt(caret.attr('width'))-20);

	if(caret.height()!=0) {
		$('#command').css('top',caret.offset().top+parseInt(caret.attr('height')));
		$('#symbol').css('top',caret.offset().top+parseInt(caret.attr('height')));
	}
	else {
		$('#command').css('top',caret.offset().top);
		$('#symbol').css('top',caret.offset().top);
	}

	
	$('#command').show();
	$('#symbol').show();
	
	slashFlag=1;
	
	comhead=$('<div></div>').appendTo($('#command'));
	comcaret=$('<span></span>').appendTo(comhead);
	
	comhead.attr('level',0);
	comhead.attr('width',0);
	
	comcaret.attr('level',2);
//	caret.css('position',"absolute");
	comcaret.css('left',0);
	comcaret.css('bottom',0);
	comcaret.attr('width',0);
	comcaret.attr('height',18);
	comcaret.attr('class',"starter");
	
	$('#comcaret').show();
	showCaretCommand();
}

// temporarily not working
function fetchParent() {
	if(caret==head) {
		return head;
	}
	else{
		return caret.parent();	
	}
	
}

function skipOperatorsDown(node) {  // there is a bug try to make it better.

	var temp;
	var flag=0;
	
	
	if(node.attr('class')!="operator"||node.children().length<=0)
	{
		return node.parent();
	}
	
	temp=node;
	
	while(!flag)  
	{	
		node=temp.children();
		node.each(function (o) {
			if($(this).attr('class')!="operator")
			{	
				temp=$(this);
				flag=1;
				return false;
			}
			else if($(this).attr('flag')=="subOperator"&&$(this).children().length>0) {
					temp=$(this);
					return false;
						
			}
		
		
		})
		
	
	}
	
		
	return temp;

}

function skipOperatorsUp(node) {
	
	node=node.parent();
	
	while(node.attr('class')=="operator")  //skip operators, refined
	{	
		if(node.attr('flag')=="superOperator") {
				return node.prev();
				break;
		}
		else if(node.attr('operator')=="slash") {
				node=node.prev();
				slashFlag=1;  // something has to happen with Slash.
				break;
		}
		else if(node.parent().length>0){
				node=node.parent();
		}
		else {
			return node;
		}
	}
	
	return node;

}

function moveLeft(node) {  // it never starts with an operator node.

	if(node.prev().length>0) {
		return node.prev();	
	}
	else if(node.parent().length>0) 
	{	
		if(parseInt(node.parent().attr('level'))==0) {
			return node;
		}
		else {
			return skipOperatorsUp(node);
		}
	}
	else 
	{
		return node;
	}
}

function moveRight(node) { // it never starts with an operator node.

	if(node.next().length>0) {
		if(node.next().attr('class')!="operator") {
			return node.next();
		}	
		else {
			node=node.next();
			return skipOperatorsDown(node);
		}
	}
	else if(node.parent().length>0)
	{
		if(parseInt(node.parent().attr('level'))==0) {
			return node;
		}
		else if(node.parent().attr('flag')=="superOperator") {
			return node.parent();
		}
		else {
			node=node.parent();
			return moveRight(node);
		}
	}
	
}

function moveDown(node) {

	if(node.next().children('[operator="down"]').length>0) {
		return node.next().children('[operator="down"]').children().first();
	}
		
	else if(node.parent().length>0) 
	{	
		if(node.parent().siblings('[operator="down"]').length>0) {
			return node.parent().siblings('[operator="down"]').children().first();
		}
		else if(node.parent().attr('operator')=="up") {
			return skipOperatorsUp(node);
		}
		else {
			return node;
		}
	}	

	return node;
		
}

function moveUp(node) {

	if(node.next().children('[operator="up"]').length>0) {
		return node.next().children('[operator="up"]').children().first();
	}
		
	else if(node.parent().length>0) 
	{	
		if(node.parent().siblings('[operator="up"]').length>0) {
			return node.parent().siblings('[operator="up"]').children().first();
		}
		else if(node.parent().attr('operator')=="down") {
			return skipOperatorsUp(node);
		}
		else {
			return node;
		}
	}

	return node;
	
}

function deletion(node) {

	if(node.prev().length>0) {
		node=node.prev();
		node.next().remove();
		return node;
	}
	else if(node.parent().length>0) 
	{	
		if(node.parent().attr("level")=="0") {
			return node;	
		}
		else {
			node=skipOperatorsUp(node);
			node.next().remove();
			return node;	
		}
	}
	else 
	{
		return node;
	}
}

function keydown(e) {  //taking care of arrow keys
	var keyCode=e.which;
	var temp;
//	alert(keyCode);
	if(!slashFlag) {
		if(keyCode==8){ //delete
			caret=deletion(caret);
			updateTree(head);
		}
	
		else if(keyCode==40){ //down
				caret=moveDown(caret);
		}
		else if(keyCode==38){ //up
			caret=moveUp(caret);
		}
		else if(keyCode==37){ //left
			caret=moveLeft(caret);
		}
		else if(keyCode==39){ //right   // Making the finding right element a nested operation
			caret=moveRight(caret);
		}
		else {
			return 0;
		}
		showCaret();
	}
	else if(slashFlag) {
		if(keyCode==8){ //delete
			comcaret=deletion(comcaret);
			updateTree(comhead);
		}

		else if(keyCode==37){ //left
			comcaret=moveLeft(comcaret);
		}
		else if(keyCode==39){ //right   // Making the finding right element a nested operation
			comcaret=moveRight(comcaret);
		}
		else {
			return 0;
		}
		showCaretCommand();
	}

} 

function maxWidthChildren(node) {
	var maxWidth=0;
	var temp;
	
	if(node.children().length>0) {
		node.children().each(function (o) {
			if((temp=parseInt($(this).attr('width')))>maxWidth) {
				maxWidth=temp;
			}	
		})
		return maxWidth;
	}
	else
	{
		return 0;
	}
}

function upOffSetChildren(node) {
	var tempOffset=0;
	var maxOffset=0;
	
	if(node.children().length>0) {
		node.children().each(function(o) {
			if($(this).attr('flag')=="superOperator") {
				tempOffset=parseInt($(this).attr('upOffset'));
				maxOffset=Math.max(maxOffset,tempOffset);
			}
		})
		return maxOffset;
	}
	else {
		return 0;
	}
}

function downOffSetChildren(node) {
	var tempOffset=0;
	var maxOffset=0;
	
	if(node.children().length>0) {
		node.children().each(function(o) {
			if($(this).attr('flag')=="superOperator") {
				tempOffset=parseInt($(this).attr('downOffset'));
				maxOffset=Math.max(maxOffset,tempOffset);
			}
		})
		return maxOffset;
	}
	else {
		return 0;
	}
}

// we follow the philosophy of upoffset and downoffsets.

// then we should unify the nomenclature of up and down. 

//=========================================================

function offSetForOverline(node) {
	var operatorNode;
	var upOffset=0;
	var downOffset=0;
	var selfHeight;
	var selfWidth; // for left alignment in fraction
	var height;
	
	var upOffsetTop=0;
	var downOffsetTop=0;
	var upOffsetBottom=0;
	var downOffsetBottom=0;
	
	var heightTop=0;
	var heightBottom=0;
	
	var widthThis=0;
	
	node.attr('upOffSet',0);
	node.attr('downOffSet',0);
	
	operatorNode=node.children();
	selfHeight=parseInt(node.attr('height'));
	selfWidth=parseInt(node.attr('width'));
	
	if(operatorNode.length<=0) {s
		return 0;
	}
	
	else {  
			operatorNode.each(function(o){
				element=$(this);
				if(element.attr('operator')=="down"){
					widthThis=parseInt(element.attr('width'));
					heightBottom=parseInt(element.attr('height'));
					upOffsetBottom=upOffSetChildren(element);
					downOffsetBottom=downOffSetChildren(element);
					element.css('bottom',0);  // no need to compensate for Downoffset
					element.css('left',0); // no need to compensate for Left Alignment
					node.attr('upOffSet',upOffsetBottom+heightBottom-selfHeight+2);
					node.attr('downOffSet',downOffsetBottom);
				}
				else if(element.attr('operator')=="line"){
					element.css('bottom',upOffsetBottom+heightBottom);
					element.css('left',0);
					element.css('width',selfWidth);
				}
				
			})

	}
}

function offSetForGeneral(node) {
	var operatorNode;
	var upOffset=0;
	var downOffset=0;
	var selfHeight;
	var selfWidth; // for left alignment in fraction
	var height;
	
	var upOffsetTop=0;
	var downOffsetTop=0;
	var upOffsetBottom=0;
	var downOffsetBottom=0;
	
	var heightTop=0;
	var heightBottom=0;
	
	var widthThis=0;
	
	node.attr('upOffSet',0);
	node.attr('downOffSet',0);
	
	operatorNode=node.children();
	selfHeight=parseInt(node.attr('height'));
	selfWidth=parseInt(node.attr('width'));
	
	if(operatorNode.length<=0) {s
		return 0;
	}
	
	else {  
			operatorNode.each(function(o){
				element=$(this);
				if(element.attr('operator')=="up"){
					widthThis=parseInt(element.attr('width'));
					heightTop=parseInt(element.attr('height'));
					upOffsetTop=upOffSetChildren(element);
					downOffsetTop=downOffSetChildren(element);
					element.css('bottom',0);  // no need to compensate for Downoffset
					element.css('left',0); // no need to compensate for Left Alignment
					node.attr('upOffSet',upOffsetTop+heightTop-selfHeight);
					node.attr('downOffSet',downOffsetTop+2);
				}
			})

	}

}

function offSetForUnderline(node) {
	var operatorNode;
	var upOffset=0;
	var downOffset=0;
	var selfHeight;
	var selfWidth; // for left alignment in fraction
	var height;
	
	var upOffsetTop=0;
	var downOffsetTop=0;
	var upOffsetBottom=0;
	var downOffsetBottom=0;
	
	var heightTop=0;
	var heightBottom=0;
	
	var widthThis=0;
	
	node.attr('upOffSet',0);
	node.attr('downOffSet',0);
	
	operatorNode=node.children();
	selfHeight=parseInt(node.attr('height'));
	selfWidth=parseInt(node.attr('width'));
	
	if(operatorNode.length<=0) {s
		return 0;
	}
	
	else {  
			operatorNode.each(function(o){
				element=$(this);
				if(element.attr('operator')=="up"){
					widthThis=parseInt(element.attr('width'));
					heightTop=parseInt(element.attr('height'));
					upOffsetTop=upOffSetChildren(element);
					downOffsetTop=downOffSetChildren(element);
					element.css('bottom',0);  // no need to compensate for Downoffset
					element.css('left',0); // no need to compensate for Left Alignment
					node.attr('upOffSet',upOffsetTop+heightTop-selfHeight);
					node.attr('downOffSet',downOffsetTop+2);
				}
				else if(element.attr('operator')=="line"){
					element.css('bottom',-downOffsetTop);
					element.css('left',0);
					element.css('width',selfWidth);
				}
				
			})

	}
}

function offSetForFraction(node) {
	var operatorNode;
	var upOffset=0;
	var downOffset=0;
	var selfHeight;
	var selfWidth; // for left alignment in fraction
	var height;
	
	var upOffsetTop=0;
	var downOffsetTop=0;
	var upOffsetBottom=0;
	var downOffsetBottom=0;
	
	var heightTop=0;
	var heightBottom=0;
	
	var widthThis=0;
	
	node.attr('upOffSet',0);
	node.attr('downOffSet',0);
	
	operatorNode=node.children();
	selfHeight=parseInt(node.attr('height'));
	selfWidth=parseInt(node.attr('width'))+selfHeight*0.4;
	node.attr('width',selfWidth);
	
	if(operatorNode.length<=0) {

		return 0;
	}
	
	else {  // the only additional thing you need to do here is to align the left as well. 
	// Up and Down are designed to 
			operatorNode.each(function(o){
				element=$(this);
				if(element.attr('operator')=="up"){
					widthThis=parseInt(element.attr('width'));
					heightTop=parseInt(element.attr('height'));
					upOffsetTop=upOffSetChildren(element);
					downOffsetTop=downOffSetChildren(element);
					element.css('bottom',selfHeight*(1/2)+downOffsetTop);
					element.css('left',(selfWidth-widthThis)/2);
					node.attr('upOffSet',heightTop+upOffsetTop+downOffsetTop-selfHeight/2);
				}
				else if(element.attr('operator')=="down"){
					widthThis=parseInt(element.attr('width'));
					heightBottom=parseInt(element.attr('height'));
					upOffsetBottom=upOffSetChildren(element);
					downOffsetBottom=downOffSetChildren(element);
					element.css('left',(selfWidth-widthThis)/2);
					element.css('bottom',selfHeight/2-heightBottom-upOffsetBottom);
					node.attr('downOffSet',heightBottom+upOffsetBottom+downOffsetBottom-selfHeight/2);
				}
				else if(element.attr('operator')=="middle"){
					element.css('bottom',selfHeight/2);
					element.css('left',0);
					element.css('width',selfWidth);
				}
				
			})

	}
}

function offSetForConglam(node) {
	var operatorNode;
	var upOffset=0;
	var downOffset=0;
	var selfHeight;
	var height;
	
	var upOffsetTop=0;
	var downOffsetTop=0;
	var upOffsetBottom=0;
	var downOffsetBottom=0;
	
	var heightTop=0;
	var heightBottom=0;
	
	node.attr('upOffSet',0);
	node.attr('downOffSet',0);
	
	operatorNode=node.children();
	selfHeight=parseInt(node.attr('height'));
	
	if(operatorNode.length<=0) {

		return 0;
	}
	
	else {
			operatorNode.each(function(o){
				element=$(this);
				if(element.attr('operator')=="up")
				{
					heightTop=parseInt(element.attr('height'));
					upOffsetTop=upOffSetChildren(element);
					downOffsetTop=downOffSetChildren(element);
					element.css('bottom',selfHeight*(2/3)+downOffsetTop);
					node.attr('upOffSet',heightTop+upOffsetTop+downOffsetTop-selfHeight/3);
				}
				else if(element.attr('operator')=="down"){
					heightBottom=parseInt(element.attr('height'));
					upOffsetBottom=upOffSetChildren(element);
					downOffsetBottom=downOffSetChildren(element);
					element.css('bottom',selfHeight/3-heightBottom-upOffsetBottom);
					node.attr('downOffSet',heightBottom+upOffsetBottom+downOffsetBottom-selfHeight/3);
				}
				
			})

	}
	
}

//===============================================

//(we need to make it more dynamic)

function fetchCommand(node) {

	var children=node.children();
	var command='';
	
	if(children.length<=0) {
		return 0;
	}
	else {
		children.each(function (o) {
			command+=$(this).text();
		}) 
	}
	
	return command;
}

function executeCommand(string) {
	var fn=window[string];
	fn(caret);
	showCaret();
}

function updateTree(node) { //left first then right, from left to right. 
	var children;
	var tempCaret;
	var oldWidth=0;
	var oldHeight=0;
	
// you can not get any information from your parents.
	children=node.children();
	tempCaret=node.children().first();
//	tempCaret.css('left',0);
//	tempCaret.css('bottom',0);
	children.each(function (o) { 
		var element=$(this);    
		if(element.children().length>0) {
			updateTree($(this));
		}  
		if(element.attr('operator')=="conglam") {    //we need to have a dynamic choice of functions
			element.attr('width',maxWidthChildren(element));	
			offSetForConglam(element);
		}
		else if(element.attr('operator')=="fraction") {
			element.attr('width',maxWidthChildren(element));	
			offSetForFraction(element);
		}
		else if(element.attr('operator')=="overline") {
			element.attr('width',maxWidthChildren(element));	
			offSetForOverline(element);
		}
		else if(element.attr('operator')=="underline") {
			element.attr('width',maxWidthChildren(element));	
			offSetForUnderline(element);
		}
		else if(element.attr('operator')=="matrix") {
			element.attr('width',maxWidthChildren(element));	
			offSetForMatrix(element);
		}
		else if(element.attr('operator')=="row") {
//			element.attr('width',maxWidthChildren(element));	done inside offset.
			offSetForMatrix(element);
		}
		else if(element.attr('flag')=="superOperator"){
			 offSetForGeneral(element);
		}
		oldWidth+=parseInt(element.attr('width'));
		element.parent().attr('width',oldWidth);
		
		if(element.parent().attr('flag')!="superOperator") {
		
			if(element.height()!=0) { // by passing the first element
				oldHeight=(oldHeight>parseInt(element.attr('height')))?oldHeight:parseInt(element.attr('height'));		
			}
			else {
				oldHeight=parseInt(element.attr('height'));
			}
			element.parent().attr('height',oldHeight);
	
		}
	
		
		if(element.attr('flag')!="subOperator") {
				thisLeft=parseInt(tempCaret.css('left').toString(),10)+parseInt(tempCaret.attr('width'));
				thisBottom=parseInt(tempCaret.css('bottom').toString(),10);
				element.css('left',thisLeft);
				element.css('bottom',thisBottom);	
		}
		else {  //for subOperator only
				; // job has been done in offSetForConglam()
		}
		tempCaret=element;
	}) 
	
}

function endCommand() {
	var command;
	
	command=fetchCommand(comhead);
	
	$('#command').empty();
	slashFlag=0;
	$('#command').hide();
	$('#symbol').hide();
	$('#comcaret').hide();
	
	executeCommand(command);
	
	
}

function findTopParent(node) {
	
	var parent=node;
	var topParent=null;
	
	while (parent.length>0)
	{	
		if(parent.attr('level')=='0')
		{
			topParent=parent;
			break;
		}
		parent=parent.parent();
		
	}
	
	return topParent;
}

function insertElementCommand(keyCode){
	
	var level;
	var thisLeft,thisBottom;
	
	level=parseInt(comcaret.attr('level')); 
	
	thisLeft=parseInt(comcaret.css('left').toString(),10)+parseInt(comcaret.attr('width'));
	thisBottom=parseInt(comcaret.css('bottom').toString(),10);
	
	comcaret=$('<span>'+String.fromCharCode(keyCode)+'</span>').insertAfter(comcaret); 			
	comcaret.attr('level',level);
	comcaret.attr('width',comcaret.width()); //report its own width.
	comcaret.attr('height',comcaret.height()); //report its own height.

	comcaret.css('left',thisLeft);
	comcaret.css('bottom',thisBottom);
//	caret.css('position',"absolute");
	
	updateTree(comhead);
}

function insertElement(keyCode,message) {
	var level;
	var thisLeft,thisBottom;
	
	level=parseInt(caret.attr('level')); 
	
	thisLeft=parseInt(caret.css('left').toString(),10)+parseInt(caret.attr('width'));
	thisBottom=parseInt(caret.css('bottom').toString(),10);
	
	caret=$('<span>'+String.fromCharCode(keyCode)+'</span>').insertAfter(caret); 			
	caret.attr('level',level);
	caret.attr('width',caret.width()); //report its own width.
	caret.attr('height',caret.height()); //report its own height.

	caret.css('left',thisLeft);
	caret.css('bottom',thisBottom);
	
	if(message=="greek"){
		caret.css('font-family',"STIXGeneral-Italic");
	}  
	else if(message=="math"){
		caret.css('font-family',"STIXGeneral-Regular");
	}

//	caret.css('position',"absolute");

	
	updateTree(head);
} //exported

function operatorType(keyCode) {
	if(keyCode==94) {
		return "up";
	}
	else if(keyCode==95) {
		return "down";
	}
}

function insertOperator(keyCode) {  //adding manual positioning
	var level;
	var parent=null; // locate parent.
	var parentLeft,parentbBottom,thisLeft,thisBottom;
	
	level=parseInt(caret.attr('level')); 
	
	// should add interlock with slash mode flag with ^ and _, maybe outside;
	
	if (keyCode==92) { // the slash operator
	
		prepareCommand();
		
	}
	
	else if(keyCode==32) { // spacebar

		endCommand();
	}

//	Taking care of ^ and _ conglammerations.
	else if(keyCode==94||keyCode==95) {
	
		if(caret.attr('operator')=="conglam") { // if conglammeration already exists, inserting after existing one
			if(caret.children('[operator="'+operatorType(keyCode)+'"]').length>0) // if this type node already exists
			{ //note the way of selector usage
				caret=caret.children('[operator="'+operatorType(keyCode)+'"]').children().last();
				return; //insert after existing ones
			}
			else { // if not, then creating it
				parent=caret.prev();
				//caret=caret;
			}
		}
		else if(caret.next().attr('operator')=="conglam") { // if conglammeration already exists, inserting before existing one
			if(caret.next().children('[operator="'+operatorType(keyCode)+'"]').length>0) // if this type node already exists
			{
				caret=caret.next().children('[operator="'+operatorType(keyCode)+'"]').children().last();
				return; //insert after existing ones
			}
			else { // if not, then creating it
				parent=caret;
				caret=caret.next();
			}
		}
		else { // conglammeration doesn't exist.
			parent=caret;
			caret=$('<span></span>').insertAfter(caret); 			
			caret.attr('level',level);
			caret.attr('class',"operator");
			caret.attr('flag',"superOperator");
			caret.attr('operator',"conglam");
			caret.attr('width',0);
			caret.attr('height',parseInt(parent.attr('height')));
//			caret.css('position',"absolute");
		}
			//Conglameration Node
		// getting parent left and bottom;
		
		parentLeft=parseInt(parent.css('left').toString(),10);
		parentBottom=parseInt(parent.css('bottom').toString(),10);
		
		
		thisLeft=parentLeft+parseInt(parent.attr('width'));
		
		caret.css('bottom',parentBottom);  //position for the conglammeration node
		caret.css('left',thisLeft);
		
		// Add Operator Node, Operator only changes bottom position
			
		caret=$('<span></span>').appendTo(caret);
		caret.attr('level',level);
		caret.attr('operator',operatorType(keyCode));
		caret.attr('class',"operator");
		caret.attr('flag',"subOperator");
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',0);
			
		// Add Content Node
		caret=$('<span></span>').appendTo(caret);
		caret.attr('level',level+1);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));
	}

	updateTree(head);
}

function keypress(e) {
	if(e.ctrlKey || e.metaKey)
    {
        return;
    }
    var keyCode = e.which;


//	alert(keyCode);
	
	if(!slashFlag) {
		if(keyCode==94||keyCode==95||keyCode==92||keyCode==32) { // if operator ^, _ \ and spacebar
	    	insertOperator(keyCode);
			showCaret();
		}
		else if(keyCode==8||keyCode==37||keyCode==39||keyCode==38||keyCode==13) { //bypassing keydown events
			;// deletion, up, down ,left and right.
		}
		else {
			insertElement(keyCode);
			showCaret();
		}
	}
	
	else if(slashFlag) {
		if(keyCode==32) { // if operator ^, _ \ and spacebar
	    	insertOperator(keyCode);
			showCaretCommand();
		}
		else if(keyCode==8||keyCode==37||keyCode==39||keyCode==40||keyCode==38||keyCode==13) { //bypassing keydown events
			;// deletion, up, down ,left and right.
		}
		else {
			insertElementCommand(keyCode);
			showCaretCommand();
		}
	}

}  // exported

$(document).keypress(keypress);
$(document).keydown(keydown);
$(document).ready(prepareEditor);

// there is a central dispatch function to determine which operator to call;

//Following are all the operator functions needed. We need to know how to add them to browser dynamically depending on user demand;

function sqrt(node) {
	;
}

function overbar(node) {
	;
}

function underbar(node) {
	;
}
// we can packaging the similar codes. Ask Qingchun to figure out what to do.
function overline(node) {
		var tempCaret;
		var parent=null;
		var level;
		var parentLeft,parentBottom,thisLeft,thisBottom;

		level=parseInt(node.attr('level')); 		
	// inserting the fraction node;
	// normalize the node;
		parent=node;
		
		caret=$('<span></span>').insertAfter(parent); 			
		caret.attr('level',level);
		caret.attr('class',"operator");
		caret.attr('operator',"overline");
		caret.attr('flag',"superOperator");
		caret.attr('width',0);
		caret.attr('height',parseInt(parent.attr('height')));

		// getting parent left and bottom;
		
		parentLeft=parseInt(parent.css('left').toString(),10);
		parentBottom=parseInt(parent.css('bottom').toString(),10);
		
		
		thisLeft=parentLeft+parseInt(parent.attr('width'));
		
		caret.css('bottom',parentBottom);  //position for the conglammeration node
		caret.css('left',thisLeft);
		
		// Add Up and Down Nodes, Operator  changes both bottom and left position; It has to be centered.
		
		parent=caret;
		
		tempCaret=$('<span></span>').appendTo(parent);
		tempCaret.attr('level',level);
		tempCaret.attr('operator','down');
		tempCaret.attr('class',"operator");
		tempCaret.attr('flag',"subOperator");
		tempCaret.css('bottom',0);
		tempCaret.css('left',0);
		tempCaret.attr('width',0);
		tempCaret.attr('height',0);
			
		// Add Content Node
		caret=$('<span></span>').appendTo(tempCaret);
		caret.attr('level',level);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));
		
		tempCaret=$('<span></span>').appendTo(parent);
		tempCaret.attr('level',level);
		tempCaret.attr('operator','line');
		tempCaret.attr('class',"operator");
		tempCaret.attr('flag',"subOperator");
		tempCaret.css('bottom',0);
		tempCaret.css('left',0);
		tempCaret.attr('width',0);
		tempCaret.attr('height',0);
	

}

function underline(node) {
		var tempCaret;
		var parent=null;
		var level;
		var parentLeft,parentBottom,thisLeft,thisBottom;

		level=parseInt(node.attr('level')); 		
	// inserting the fraction node;
	// normalize the node;
		parent=node;
		
		caret=$('<span></span>').insertAfter(parent); 			
		caret.attr('level',level);
		caret.attr('class',"operator");
		caret.attr('operator',"underline");
		caret.attr('flag',"superOperator");
		caret.attr('width',0);
		caret.attr('height',parseInt(parent.attr('height')));

		// getting parent left and bottom;
		
		parentLeft=parseInt(parent.css('left').toString(),10);
		parentBottom=parseInt(parent.css('bottom').toString(),10);
		
		
		thisLeft=parentLeft+parseInt(parent.attr('width'));
		
		caret.css('bottom',parentBottom);  //position for the conglammeration node
		caret.css('left',thisLeft);
		
		// Add Up and Down Nodes, Operator  changes both bottom and left position; It has to be centered.
		
		parent=caret;
		
		tempCaret=$('<span></span>').appendTo(parent);
		tempCaret.attr('level',level);
		tempCaret.attr('operator','up');
		tempCaret.attr('class',"operator");
		tempCaret.attr('flag',"subOperator");
		tempCaret.css('bottom',0);
		tempCaret.css('left',0);
		tempCaret.attr('width',0);
		tempCaret.attr('height',0);
			
		// Add Content Node
		caret=$('<span></span>').appendTo(tempCaret);
		caret.attr('level',level);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));
		
		tempCaret=$('<span></span>').appendTo(parent);
		tempCaret.attr('level',level);
		tempCaret.attr('operator','line');
		tempCaret.attr('class',"operator");
		tempCaret.attr('flag',"subOperator");
		tempCaret.css('bottom',0);
		tempCaret.css('left',0);
		tempCaret.attr('width',0);
		tempCaret.attr('height',0);
	
}
// reporting its size and positioning in the right way.
function frac(node) {
		var upCaret,downCaret,middleCaret;
		var parent=null;
		var level;
		var parentLeft,parentBottom,thisLeft,thisBottom;

		level=parseInt(node.attr('level')); 		
	// inserting the fraction node;
	// normalize the node;
		parent=node;
		
		caret=$('<span></span>').insertAfter(parent); 			
		caret.attr('level',level);
		caret.attr('class',"operator");
		caret.attr('operator',"fraction");
		caret.attr('flag',"superOperator");
		caret.attr('width',0);
		caret.attr('height',parseInt(parent.attr('height')));

		// getting parent left and bottom;
		
		parentLeft=parseInt(parent.css('left').toString(),10);
		parentBottom=parseInt(parent.css('bottom').toString(),10);
		
		
		thisLeft=parentLeft+parseInt(parent.attr('width'));
		
		caret.css('bottom',parentBottom);  //position for the conglammeration node
		caret.css('left',thisLeft);
		
		// Add Up and Down Nodes, Operator  changes both bottom and left position; It has to be centered.
		
			
		upCaret=$('<span></span>').appendTo(caret);
		upCaret.attr('level',level);
		upCaret.attr('operator','up');
		upCaret.attr('class',"operator");
		upCaret.attr('flag',"subOperator");
		upCaret.css('bottom',0);
		upCaret.css('left',0);
		upCaret.attr('width',0);
		upCaret.attr('height',0);
		
		middleCaret=$('<span></span>').appendTo(caret);
		middleCaret.attr('level',level);
		middleCaret.attr('operator','middle');
		middleCaret.attr('class',"operator");
		middleCaret.attr('flag',"subOperator");
		middleCaret.css('bottom',0);
		middleCaret.css('left',0);
		middleCaret.attr('width',0);
		middleCaret.attr('height',0);
		
		downCaret=$('<span></span>').appendTo(caret);
		downCaret.attr('level',level);
		downCaret.attr('operator','down');
		downCaret.attr('class',"operator");
		downCaret.attr('flag',"subOperator");
		downCaret.css('bottom',0);
		downCaret.css('left',0);
		downCaret.attr('width',0);
		downCaret.attr('height',0);
			
		// Add Content Node
		caret=$('<span></span>').appendTo(downCaret);
		caret.attr('level',level+1);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));
		
		caret=$('<span></span>').appendTo(upCaret);
		caret.attr('level',level+1);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));
		
		// and Caret settle in the upCaret;
	
}

function mathfrak(node) {
		
		var tempCaret;
		var parent=null;
		var level;
		var parentLeft,parentBottom,thisLeft,thisBottom;

		level=parseInt(node.attr('level')); 		
	// inserting the fraction node;
	// normalize the node;
		parent=node;
		
		caret=$('<span></span>').insertAfter(parent); 			
		caret.attr('level',level);
		caret.attr('class',"operator");
		caret.attr('operator',"mathfrak");
		caret.attr('flag',"superOperator");
		caret.attr('width',0);
		caret.attr('height',parseInt(parent.attr('height')));

		// getting parent left and bottom;
		
		parentLeft=parseInt(parent.css('left').toString(),10);
		parentBottom=parseInt(parent.css('bottom').toString(),10);
		
		
		thisLeft=parentLeft+parseInt(parent.attr('width'));
		
		caret.css('bottom',parentBottom);  //position for the conglammeration node
		caret.css('left',thisLeft);
		
		// Add Up and Down Nodes, Operator  changes both bottom and left position; It has to be centered.
		
		parent=caret;
		
		tempCaret=$('<span></span>').appendTo(parent);
		tempCaret.attr('level',level);
		tempCaret.attr('operator','up');
		tempCaret.attr('class',"operator");
		tempCaret.attr('flag',"subOperator");
		tempCaret.css('bottom',0);
		tempCaret.css('left',0);
		tempCaret.attr('width',0);
		tempCaret.attr('height',0);
		tempCaret.attr('font','mathfrak');
			
		// Add Content Node
		caret=$('<span></span>').appendTo(tempCaret);
		caret.attr('level',level);
		caret.css('bottom',0);
		caret.css('left',0);
		caret.attr('width',0);
		caret.attr('height',heightCaret(caret));

	
}


